package com.felix.thread;

import java.util.concurrent.ConcurrentHashMap;

/**
 * ThreadTest
 *
 * @author xuejinhua
 * @date 2019/1/23 9:34
 */

public class ThreadTest {


    public static final String Lock = "lock";


    public final Object obj = new Object();


    synchronized void test1() throws InterruptedException {
        for (int i = 0; i < 5; i++) {
            Thread.sleep(1000);
            System.out.println("test1=" + i);
        }
    }


    synchronized static void test2() throws InterruptedException {
        for (int i = 0; i < 5; i++) {
            Thread.sleep(1000);
            System.out.println("test2=" + i);
        }
    }


    void test3() throws InterruptedException {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                Thread.sleep(1000);
                System.out.println("test3=" + i);
            }
        }
    }


    void test4() throws InterruptedException {
        synchronized (this.getClass()) {
            for (int i = 0; i < 5; i++) {
                Thread.sleep(1000);
                System.out.println("test4=" + i);
            }
        }
    }


    void test5() throws InterruptedException {
        synchronized (Lock) {
            for (int i = 0; i < 5; i++) {
                Thread.sleep(1000);
                System.out.println("test5=" + i);
            }
        }
    }


    void test6() throws InterruptedException {
        synchronized (obj) {
            for (int i = 0; i < 5; i++) {
                Thread.sleep(1000);
                System.out.println("test6=" + i);
            }
        }
    }

    public static void main(String[] args) {
//        SyncThread syncThread = new SyncThread();
//        Thread thread1 = new Thread(syncThread, "SyncThread1");
//        Thread thread2 = new Thread(syncThread, "SyncThread2");
//        thread1.start();
//        thread2.start();

//        Thread thread1 = new Thread(new SyncThread(), "SyncThread1");
//        Thread thread2 = new Thread(new SyncThread(), "SyncThread2");
//        thread1.start();
//        thread2.start();
        Counter counter = new Counter();
        Thread thread1 = new Thread(counter, "A");
        Thread thread2 = new Thread(counter, "B");
        thread1.start();
        thread2.start();

//        Account account = new Account("zhang san", 10000.0f);
//        AccountOperator accountOperator = new AccountOperator(account);
//        Thread[] threads = new Thread[THREAD_NUM];
//        for (int i = 0; i < THREAD_NUM; i++) {
//            threads[i] = new Thread(accountOperator, "Thread" + i);
//            threads[i].start();
//        }

//        SyncThreadNew syncThread1 = new SyncThreadNew();
//        SyncThreadNew syncThread2 = new SyncThreadNew();
//        Thread thread1 = new Thread(syncThread1, "SyncThread1");
//        Thread thread2 = new Thread(syncThread2, "SyncThread2");
//        thread1.start();
//        thread2.start();
    }

    private static final int THREAD_NUM = 5;
}

/**
 * 同步线程
 */
class SyncThread implements Runnable {
    private static int count;

    public SyncThread() {
        count = 0;
    }

    @Override
    public void run() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public int getCount() {
        return count;
    }
}

class Counter implements Runnable {
    private int count;

    public Counter() {
        count = 0;
    }

    public void countAdd() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 非synchronized代码块，未对count进行读写操作，所以可以不用synchronized
     */
    public synchronized void printCount() {
        for (int i = 0; i < 5; i++) {
            try {
                System.out.println(Thread.currentThread().getName() + " count:" + count);
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        if ("A".equals(threadName)) {
            countAdd();
        } else if ("B".equals(threadName)) {
            printCount();
        }
    }
}

class Account {
    String name;
    float amount;

    public Account(String name, float amount) {
        this.name = name;
        this.amount = amount;
    }

    //存钱
    public void deposit(float amt) {
        amount += amt;
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //取钱
    public void withdraw(float amt) {
        amount -= amt;
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public float getBalance() {
        return amount;
    }
}

/**
 * 账户操作类
 */
class AccountOperator implements Runnable {
    private Account account;

    public AccountOperator(Account account) {
        this.account = account;
    }

    @Override
    public void run() {
        synchronized (account) {
            account.deposit(500);
            account.withdraw(500);
            System.out.println(Thread.currentThread().getName() + ":" + account.getBalance());
        }
    }
}

/**
 * 同步线程
 */
class SyncThreadNew implements Runnable {
    private static int count;

    public SyncThreadNew() {
        count = 0;
    }

    public synchronized static void method() {
        for (int i = 0; i < 5; i ++) {
            try {
                System.out.println(Thread.currentThread().getName() + ":" + (count++));
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public synchronized void run() {
        method();
    }
}